home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / lists / mint / l_0799 / 509 < prev    next >
Encoding:
Internet Message Format  |  1994-08-27  |  13.4 KB

  1. From: inf2gr04@informatik.uni-frankfurt.de
  2. Posted-Date: Tue, 21 Sep 93 12:51:33 MESZ
  3. Received-Date: Tue, 21 Sep 93 12:51:34 +0200
  4. Message-Id: <9309211051.AA06364@hptest.rbi.informatik.uni-frankfurt.de>
  5. Subject: more MiNT 1.09 bugs
  6. To: mint@atari.archive.umich.edu
  7. Date: Tue, 21 Sep 93 12:51:33 MESZ
  8. Mailer: Elm [revision: 70.85]
  9.  
  10.  
  11. I encountered two problems with MiNT 1.09. First a short description,
  12. followed by context diff's to patch them. (The patches for both of them
  13. are mixed up in the same file, sorry :-).
  14.  
  15. 1.)    If you change the flow-control state of a serial device
  16.     (u:/dev/modem1, ...) with the TIOCSFLAGS ioctl() (TANDEM, RTSCTS
  17.     Bits), then you dont't get the correct state of them with
  18.     following TIOCGFLAGS ioctl()'s (they rely on the saved state
  19.     in the sg.sg_flags member of the struct tty, which is not
  20.     updated by TIOCSFLAGS calls).
  21.  
  22. 2.)    Fselect() does not work properly when several processes are  selecting
  23.     on the same file (there're no provisions to handle collisions). For
  24.     instance, if two processes are selecting on the same sets of files,
  25.     the second one doing the Fselect() is blocked forever (provided no
  26.     timeout is specified and no signals are delivered), even if the
  27.     specified descriptors become ready for doing IO. The fix requires
  28.     support from the device-drivers select() routine. The return values
  29.     from select() should be:
  30.         0 -- not ready for IO, register for selecting (not changed)
  31.         1 -- ready for IO (not changed)
  32.         2 -- collision (not ready, but no room to hold
  33.              another process for selection on that file)
  34.     All the other work is done in f_select(). Because collisions happen
  35.     rather rarely, it's not worth to make the device-drivers select()
  36.     able to hold an arbitrary number of processes for selection on the same
  37.     file or device.
  38.     The device drivers should just be able to hold one process and return
  39.     '2' at further requests to hold another process at the same time for
  40.     the same file or device (see pipe_select for example).
  41.  
  42. The following cdiffs are relative to MiNT 1.09, it would be nice if they
  43. could be applied to new MiNT versions (to Eric ...).
  44.  
  45. cheers, Kay Roemer.
  46.  
  47. *** biosfs.c.orig    Sun Sep  5 20:18:00 1993
  48. --- biosfs.c    Mon Sep 13 21:41:28 1993
  49. ***************
  50. *** 1144,1150 ****
  51. --- 1144,1154 ----
  52.                   oflags |= (ucr & 0x2) ? T_EVENP : T_ODDP;
  53.               }
  54.               if (mode == TIOCSFLAGS) {
  55. +                 ushort *sg_flags =
  56. +                     &((struct tty *)f->devinfo)->sg.sg_flags;
  57.                   flags = (*(unsigned short *)buf);
  58. +                 *sg_flags &= ~(T_RTSCTS|T_TANDEM);
  59. +                 *sg_flags |= flags & (T_RTSCTS|T_TANDEM);
  60.                   if (flags & T_EVENP) {
  61.                       ucr |= 0x6;
  62.                   } else if (flags & T_ODDP) {
  63. ***************
  64. *** 1236,1243 ****
  65.           }
  66.           if (tty) {
  67.           /* avoid collisions with other processes */
  68. !             if (!tty->rsel)
  69. !                 tty->rsel = p;
  70.           }
  71.           return 0;
  72.       } else if (mode == O_WRONLY) {
  73. --- 1240,1248 ----
  74.           }
  75.           if (tty) {
  76.           /* avoid collisions with other processes */
  77. !             if (tty->rsel)
  78. !                 return 2; /* collsion */
  79. !             tty->rsel = p;
  80.           }
  81.           return 0;
  82.       } else if (mode == O_WRONLY) {
  83. ***************
  84. *** 1246,1253 ****
  85.               return 1;
  86.           }
  87.           if (tty) {
  88. !             if (!tty->wsel)
  89. !                 tty->wsel = p;
  90.           }
  91.           return 0;
  92.       }
  93. --- 1251,1259 ----
  94.               return 1;
  95.           }
  96.           if (tty) {
  97. !             if (tty->wsel)
  98. !                 return 2; /* collision */
  99. !             tty->wsel = p;
  100.           }
  101.           return 0;
  102.       }
  103. ***************
  104. *** 1482,1489 ****
  105.       if (mousetail - mousehead)
  106.           return 1;    /* input waiting already */
  107.   
  108. !     if (!mousersel)
  109. !         mousersel = p;
  110.       return 0;
  111.   }
  112.   
  113. --- 1488,1496 ----
  114.       if (mousetail - mousehead)
  115.           return 1;    /* input waiting already */
  116.   
  117. !     if (mousersel)
  118. !         return 2; /* collision */
  119. !     mousersel = p;
  120.       return 0;
  121.   }
  122.   
  123. *** dosfile.c.orig    Mon Sep 13 18:32:46 1993
  124. --- dosfile.c    Mon Sep 13 23:02:06 1993
  125. ***************
  126. *** 11,16 ****
  127. --- 11,19 ----
  128.   static long do_dup P_((int,int));
  129.   static void unselectme P_((PROC *));
  130.   
  131. + /* wait condition for selecting processes which got collisions */
  132. + short select_coll;
  133.   /*
  134.    * first, some utility routines
  135.    */
  136. ***************
  137. *** 274,279 ****
  138. --- 277,284 ----
  139.       if (f->dev) {
  140.           (*f->dev->unselect)(f, (long)p, O_RDONLY);
  141.           (*f->dev->unselect)(f, (long)p, O_WRONLY);
  142. + /* give other processes a chance to select on this file */
  143. +         wake(SELECT_Q, (long)&select_coll);
  144.       }
  145.   
  146.       f->links--;
  147. ***************
  148. *** 957,983 ****
  149.       unsigned timeout;
  150.       long *rfdp, *wfdp, *xfdp;
  151.   {
  152. !     long rfd, wfd;
  153.       long mask, bytes;
  154.       int i, count;
  155.       FILEPTR *f;
  156.       PROC *p;
  157. !     TIMEOUT *t;
  158.       short sr;
  159.   
  160.       if (xfdp)
  161.           *xfdp = 0;
  162.   
  163.       if (rfdp) {
  164. !         rfd = *rfdp; *rfdp = 0;
  165.       }
  166.       else
  167. !         rfd = 0;
  168.       if (wfdp) {
  169. !         wfd = *wfdp; *wfdp = 0;
  170.       }
  171.       else
  172. !         wfd = 0;
  173.   
  174.       TRACE(("Fselect(%u, %lx, %lx)", timeout, rfd, wfd));
  175.       p = curproc;            /* help the optimizer out */
  176. --- 962,988 ----
  177.       unsigned timeout;
  178.       long *rfdp, *wfdp, *xfdp;
  179.   {
  180. !     long rfd, wfd, orfd, owfd;
  181.       long mask, bytes;
  182.       int i, count;
  183.       FILEPTR *f;
  184.       PROC *p;
  185. !     TIMEOUT *t = 0;
  186.       short sr;
  187.   
  188.       if (xfdp)
  189.           *xfdp = 0;
  190.   
  191.       if (rfdp) {
  192. !         orfd = rfd = *rfdp; *rfdp = 0;
  193.       }
  194.       else
  195. !         orfd = rfd = 0;
  196.       if (wfdp) {
  197. !         owfd = wfd = *wfdp; *wfdp = 0;
  198.       }
  199.       else
  200. !         owfd = wfd = 0;
  201.   
  202.       TRACE(("Fselect(%u, %lx, %lx)", timeout, rfd, wfd));
  203.       p = curproc;            /* help the optimizer out */
  204. ***************
  205. *** 985,991 ****
  206.       /* first, validate the masks */
  207.       mask = 1L;
  208.       for (i = 0; i < MAX_OPEN; i++) {
  209. !         if ( ((rfd & mask) || (wfd & mask)) && !(p->handle[i]) ) {
  210.               DEBUG(("Fselect: invalid handle: %d", i));
  211.               return EIHNDL;
  212.           }
  213. --- 990,996 ----
  214.       /* first, validate the masks */
  215.       mask = 1L;
  216.       for (i = 0; i < MAX_OPEN; i++) {
  217. !         if ( ((orfd & mask) || (owfd & mask)) && !(p->handle[i]) ) {
  218.               DEBUG(("Fselect: invalid handle: %d", i));
  219.               return EIHNDL;
  220.           }
  221. ***************
  222. *** 1001,1035 ****
  223.    * closed one of the handles.
  224.    */
  225.   
  226. -     mask = 1L;
  227.       count = 0;
  228.       curproc->wait_cond = (long)wakeselect;        /* flag */
  229.   
  230.       for (i = 0; i < MAX_OPEN; i++) {
  231.           if (rfd & mask) {
  232.               f = p->handle[i];
  233. !             if ((*f->dev->select)(f, (long)p, O_RDONLY)) {
  234.                   count++;
  235.                   *rfdp |= mask;
  236.               }
  237.           }
  238.           if (wfd & mask) {
  239.               f = p->handle[i];
  240. !             if ((*f->dev->select)(f, (long)p, O_WRONLY)) {
  241.                   count++;
  242.                   *wfdp |= mask;
  243.               }
  244.           }
  245.           mask = mask << 1L;
  246.       }
  247.   
  248.       if (count == 0) {
  249. !         /* OK, now let's set a timeout */
  250.   
  251. !         if (timeout) {
  252.               t = addtimeout((long)timeout, unselectme);
  253. -         } else {
  254. -             t = 0;
  255.           }
  256.   
  257.           sr = spl7();
  258. --- 1006,1058 ----
  259.    * closed one of the handles.
  260.    */
  261.   
  262.       count = 0;
  263.       curproc->wait_cond = (long)wakeselect;        /* flag */
  264.   
  265. + /* NOTE to the above note: since we can get here several times (in
  266. +  * case of collisions) after we've gone to sleep, we probably cannot
  267. +  * assume the filepointers are valid.
  268. +  * I'm not really sure, because `post_sig' sets curproc->wait_cond
  269. +  * to zero and then we cannot get here after we've gone to sleep. 
  270. +  */
  271. +  
  272. + retry_after_collision:
  273. +     mask = 1L;
  274. +     
  275.       for (i = 0; i < MAX_OPEN; i++) {
  276.           if (rfd & mask) {
  277.               f = p->handle[i];
  278. !             if (f) {
  279. !                 switch ((*f->dev->select)(f, (long)p, O_RDONLY)) {
  280. !                 case 1:
  281.                   count++;
  282.                   *rfdp |= mask;
  283. +                 case 0:
  284. +                 rfd &= ~mask;
  285. +                 }
  286.               }
  287.           }
  288.           if (wfd & mask) {
  289.               f = p->handle[i];
  290. !             if (f) {
  291. !                 switch ((*f->dev->select)(f, (long)p, O_WRONLY)) {
  292. !                 case 1:
  293.                   count++;
  294.                   *wfdp |= mask;
  295. +                 case 0:
  296. +                 wfd &= ~mask;
  297. +                 }
  298.               }
  299.           }
  300.           mask = mask << 1L;
  301.       }
  302.   
  303.       if (count == 0) {
  304. !     /* OK, now let's set a timeout, but only the first time we get here */
  305.   
  306. !         if (!t && timeout) {
  307.               t = addtimeout((long)timeout, unselectme);
  308.           }
  309.   
  310.           sr = spl7();
  311. ***************
  312. *** 1037,1044 ****
  313.       /* curproc->wait_cond changes when data arrives or the timeout happens */
  314.           while (curproc->wait_cond == (long)wakeselect) {
  315.               TRACE(("sleeping in Fselect"));
  316. !             sleep(SELECT_Q, (long)wakeselect);
  317.           }
  318.           spl(sr);
  319.   
  320.       /* we can cancel the time out now (if it hasn't already happened) */
  321. --- 1060,1076 ----
  322.       /* curproc->wait_cond changes when data arrives or the timeout happens */
  323.           while (curproc->wait_cond == (long)wakeselect) {
  324.               TRACE(("sleeping in Fselect"));
  325. !             if (rfd || wfd) {
  326. !                 sleep(SELECT_Q, (long)&select_coll);
  327. !             } else {
  328. !                 sleep(SELECT_Q, (long)wakeselect);
  329. !             }
  330.           }
  331. +         if (curproc->wait_cond == (long)&select_coll) {
  332. +             curproc->wait_cond = (long)wakeselect;
  333. +             spl(sr);
  334. +             goto retry_after_collision;
  335. +         }
  336.           spl(sr);
  337.   
  338.       /* we can cancel the time out now (if it hasn't already happened) */
  339. ***************
  340. *** 1047,1053 ****
  341.       /* OK, let's see what data arrived (if any) */
  342.           mask = 1L;
  343.           for (i = 0; i < MAX_OPEN; i++) {
  344. !             if (rfd & mask) {
  345.                   f = p->handle[i];
  346.                   if (f) {
  347.                       bytes = 1L;
  348. --- 1079,1085 ----
  349.       /* OK, let's see what data arrived (if any) */
  350.           mask = 1L;
  351.           for (i = 0; i < MAX_OPEN; i++) {
  352. !             if (orfd & mask) {
  353.                   f = p->handle[i];
  354.                   if (f) {
  355.                       bytes = 1L;
  356. ***************
  357. *** 1058,1064 ****
  358.                       }
  359.                   }
  360.               }
  361. !             if (wfd & mask) {
  362.                   f = p->handle[i];
  363.                   if (f) {
  364.                       bytes = 1L;
  365. --- 1090,1096 ----
  366.                       }
  367.                   }
  368.               }
  369. !             if (owfd & mask) {
  370.                   f = p->handle[i];
  371.                   if (f) {
  372.                       bytes = 1L;
  373. ***************
  374. *** 1071,1089 ****
  375.               }
  376.               mask = mask << 1L;
  377.           }
  378. !     }
  379.   
  380.       /* at this point, we either have data or a time out */
  381.       /* cancel all the selects */
  382.       mask = 1L;
  383.   
  384.       for (i = 0; i < MAX_OPEN; i++) {
  385. !         if (rfd & mask) {
  386.               f = p->handle[i];
  387.               if (f)
  388.                   (*f->dev->unselect)(f, (long)p, O_RDONLY);
  389.           }
  390. !         if (wfd & mask) {
  391.               f = p->handle[i];
  392.               if (f)
  393.                   (*f->dev->unselect)(f, (long)p, O_WRONLY);
  394. --- 1103,1127 ----
  395.               }
  396.               mask = mask << 1L;
  397.           }
  398. !     } else if (t) {
  399.   
  400. +     /* in case data arrived after a collsion, there
  401. +      * could be a timeout pending even if count > 0
  402. +      */
  403. +         canceltimeout(t);
  404. +     }
  405. +     
  406.       /* at this point, we either have data or a time out */
  407.       /* cancel all the selects */
  408.       mask = 1L;
  409.   
  410.       for (i = 0; i < MAX_OPEN; i++) {
  411. !         if (orfd & mask) {
  412.               f = p->handle[i];
  413.               if (f)
  414.                   (*f->dev->unselect)(f, (long)p, O_RDONLY);
  415.           }
  416. !         if (owfd & mask) {
  417.               f = p->handle[i];
  418.               if (f)
  419.                   (*f->dev->unselect)(f, (long)p, O_WRONLY);
  420. ***************
  421. *** 1091,1096 ****
  422. --- 1129,1138 ----
  423.           mask = mask << 1L;
  424.       }
  425.   
  426. +     /* wake other processes which got a collision */
  427. +     if (orfd || owfd)
  428. +         wake(SELECT_Q, (long)&select_coll);
  429.       TRACE(("Fselect: returning %d", count));
  430.       return count;
  431.   }
  432. *** pipefs.c.orig    Mon Sep 13 21:42:50 1993
  433. --- pipefs.c    Mon Sep 13 21:44:34 1993
  434. ***************
  435. *** 1010,1018 ****
  436.               return 1;
  437.           }
  438.   
  439. ! /* BUG: multiple selects fail, only the first one works */
  440. !         if (!p->rsel)
  441. !             p->rsel = proc;
  442.           return 0;
  443.       } else if (mode == O_WRONLY) {
  444.           p = (f->flags & O_HEAD) ? this->inp : this->outp;
  445. --- 1010,1018 ----
  446.               return 1;
  447.           }
  448.   
  449. !         if (p->rsel)
  450. !             return 2; /* collision */
  451. !         p->rsel = proc;
  452.           return 0;
  453.       } else if (mode == O_WRONLY) {
  454.           p = (f->flags & O_HEAD) ? this->inp : this->outp;
  455. ***************
  456. *** 1024,1031 ****
  457.           if (j >= PIPESIZ) j = 0;
  458.           if (j != p->head || p->readers <= 0)
  459.               return 1;    /* data may be written */
  460. !         if (!p->wsel)
  461. !             p->wsel = proc;
  462.           return 0;
  463.       }
  464.       return 0;
  465. --- 1024,1032 ----
  466.           if (j >= PIPESIZ) j = 0;
  467.           if (j != p->head || p->readers <= 0)
  468.               return 1;    /* data may be written */
  469. !         if (p->wsel)
  470. !             return 2; /* collsion */
  471. !         p->wsel = proc;
  472.           return 0;
  473.       }
  474.       return 0;
  475. *** proc.c.orig    Mon Sep 13 21:22:00 1993
  476. --- proc.c    Mon Sep 13 21:23:40 1993
  477. ***************
  478. *** 608,616 ****
  479.   {
  480.       PROC *p = (PROC *)param;
  481.       short s;
  482.       s = spl7();    /* block interrupts */
  483. !     if(p->wait_cond == (long)wakeselect) {
  484.           p->wait_cond = 0;
  485.       }
  486.       if (p->wait_q == SELECT_Q) {
  487. --- 608,618 ----
  488.   {
  489.       PROC *p = (PROC *)param;
  490.       short s;
  491. !     extern short select_coll; /* in dosfile.c */
  492. !     
  493.       s = spl7();    /* block interrupts */
  494. !     if(p->wait_cond == (long)wakeselect ||
  495. !        p->wait_cond == (long)&select_coll) {
  496.           p->wait_cond = 0;
  497.       }
  498.       if (p->wait_q == SELECT_Q) {
  499. *** signal.c.orig    Fri Sep 17 15:32:58 1993
  500. --- signal.c    Fri Sep 17 15:54:14 1993
  501. ***************
  502. *** 56,62 ****
  503.       int sig;
  504.   {
  505.       ulong sigm;
  506.   /* if process is ignoring this signal, do nothing
  507.    * also: signal 0 is SIGNULL, and should never be delivered through
  508.    * the normal channels (indeed, it's filtered out in dossig.c,
  509. --- 56,64 ----
  510.       int sig;
  511.   {
  512.       ulong sigm;
  513. !     short sr;
  514. !     extern short select_coll; /* in dosfile.c */
  515. !     
  516.   /* if process is ignoring this signal, do nothing
  517.    * also: signal 0 is SIGNULL, and should never be delivered through
  518.    * the normal channels (indeed, it's filtered out in dossig.c,
  519. ***************
  520. *** 83,93 ****
  521.       if ( (p->sigmask & sigm) != 0 )
  522.           return;
  523.   
  524.   /* otherwise, make sure the process is awake */
  525.       if (p->wait_q && p->wait_q != READY_Q) {
  526. !         short sr = spl7();
  527. !         if (p->wait_q == SELECT_Q)
  528. !             p->wait_cond = 0;
  529.           rm_q(p->wait_q, p);
  530.           add_q(READY_Q, p);
  531.           spl(sr);
  532. --- 85,104 ----
  533.       if ( (p->sigmask & sigm) != 0 )
  534.           return;
  535.   
  536. + /* Notify p, if p is selecting. After a wake(SELECT_Q, (long)&select_coll)
  537. +  * p might be on READY_Q with p->wait_cond == &select_coll. Posting p a
  538. +  * signal then requires clearing p->wait_cond even if p is not on SELECT_Q.
  539. +  */
  540. +     sr = spl7();
  541. +     if (p->wait_cond == (long)wakeselect ||
  542. +         p->wait_cond == (long)&select_coll) {
  543. +         p->wait_cond = 0;
  544. +     }
  545. +     spl(sr);
  546. +     
  547.   /* otherwise, make sure the process is awake */
  548.       if (p->wait_q && p->wait_q != READY_Q) {
  549. !         sr = spl7();
  550.           rm_q(p->wait_q, p);
  551.           add_q(READY_Q, p);
  552.           spl(sr);
  553.  
  554.